/*
 * @Author: Wangjun
 * @Date: 2023-04-13 11:11:47
 * @LastEditTime: 2024-03-09 11:01:56
 * @LastEditors: wangjun haodreams@163.com
 * @Description:
 * @FilePath: \aexp\function.go
 * hnxr
 */
package aexp

import (
	"errors"
	"math"
)

type Function func(x ...any) (any, error)

// 全局函数
var globalFunction = map[string]Function{
	"IF":  IF,  //逻辑判断
	"MAX": Max, //最大值
	"MIN": Min, //最小值
	"SUM": Sum, //求和
	"AVG": Avg, //平均值
	"ABS": ABS, //绝对值
	"NOT": NOT, //逻辑非
}

/**
 * @description: 是否是内置函数
 * @param {string} name
 * @return {*}
 */
func IsBuiltinFunction(name string) bool {
	_, ok := globalFunction[name]
	return ok
}

// 注册一个函数
// 使用 包名直接注册的是全局函数，使用Expr 注册的只在Expr内部可用，是私有方法
func RegisterFunction(name string, f Function) {
	globalFunction[name] = f
}

func MAX(xs ...any) (any, error) {
	if len(xs) < 2 {
		return nil, errors.New("[MAX]参数错误")
	}
	return eval(xs[0], xs[1], "", func(x1 float64, y1 float64) (float64, error) {
		if x1 < y1 {
			return y1, nil
		}
		return x1, nil
	})
}

func MIN(xs ...any) (any, error) {
	if len(xs) < 2 {
		return nil, errors.New("[MIN]参数错误")
	}
	return eval(xs[0], xs[1], "", func(x1 float64, y1 float64) (float64, error) {
		if x1 > y1 {
			return y1, nil
		}
		return x1, nil
	})
}

func IF(xs ...any) (any, error) {
	if len(xs) < 3 {
		return nil, errors.New("[IF]参数错误")
	}
	x1, ok := xs[0].(float64)
	if !ok {
		return nil, errors.New("[IF]参数错误")
	}
	if x1 != 0 {
		return xs[1], nil
	}
	return xs[2], nil
}

func Min(xs ...any) (any, error) {
	min := 0.0
	found := false
	for _, x := range xs {
		switch vs := x.(type) {
		case float64:
			if !found {
				min = vs
				found = true
				continue
			}
			if vs < min {
				min = vs
			}
		case []float64:
			for _, v := range vs {
				if !found {
					min = v
					found = true
					continue
				}
				if v < min {
					min = v
				}
			}
		default:
			continue
		}
	}
	return min, nil
}

func Max(xs ...any) (any, error) {
	max := 0.0
	found := false
	for _, x := range xs {
		switch vs := x.(type) {
		case float64:
			if !found {
				max = vs
				found = true
				continue
			}
			if vs > max {
				max = vs
			}
		case []float64:
			for _, v := range vs {
				if !found {
					max = v
					found = true
					continue
				}
				if v > max {
					max = v
				}
			}
		default:
			continue
		}
	}
	return max, nil
}

func Sum(xs ...any) (any, error) {
	sum := 0.0
	for _, x := range xs {
		switch vs := x.(type) {
		case float64:
			sum += vs
		case []float64:
			for _, v := range vs {
				sum += v
			}
		default:
			continue
		}
	}
	return sum, nil
}

func Avg(xs ...any) (any, error) {
	sum := 0.0
	count := 0
	for _, x := range xs {
		switch vs := x.(type) {
		case float64:
			sum += vs
			count++
		case []float64:
			for _, v := range vs {
				sum += v
				count++
			}
		default:
			continue
		}
	}
	if count == 0 {
		return 0, errors.New("'AVG'参数数量小于1")
	}
	return sum / float64(count), nil
}

func ABS(xs ...any) (any, error) {
	if len(xs) < 1 {
		return nil, errors.New("'ABS'参数错误")
	}
	if p, ok := xs[0].(float64); ok {
		return math.Abs(p), nil
	}
	return nil, errors.New("'ABS'参数错误")
}

func NOT(xs ...any) (any, error) {
	if len(xs) < 1 {
		return nil, errors.New("'NOT'参数错误")
	}
	if p, ok := xs[0].(float64); ok {
		if int(p) != 0 {
			return 1, nil
		}
		return 0, nil
	}

	return nil, errors.New("'NOT'参数错误")
}
